
package Procesos;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import negocio.AtributoXML;
import negocio.ElementoDTD;
import negocio.EntidadXML;
import negocio.EstructuraDTD;
/**
 *
 * @author Emiliano
 */
public class GestorEstructuraDTD {
    
    public static String procesarComparacionDTD(String textoDTD) {

        ArrayList<ElementoDTD> elementos = new ArrayList<ElementoDTD>();

//         Se divide el contenido total del dtd en renglones
        String lineasDTD[] = textoDTD.split("\\n");
        for (int i = 0; i < lineasDTD.length; i++) {

            ArrayList<ElementoDTD> listaHijosDTD = new ArrayList<ElementoDTD>();

            if (!lineasDTD[i].trim().equals("")) {

                if (elementos.size() == 0) {
                    //es raiz
                    String renglon[] = lineasDTD[i].split(" ");//guarda en un arrays cada una de las palabras de la linea

                    ElementoDTD root = new ElementoDTD();

                    root.setNombre(renglon[1].trim()); //posición 1 para no guardar ELEMENT o ATTLIST
                    root.setRoot(true);
                    root.setObligatorio(true);

                    String hijo = renglon[2].trim(); //Guarda elemento hijo
                    hijo = hijo.substring(1, hijo.length() - 1);// saca parentesis o >
                    ElementoDTD hijoDTD = new ElementoDTD();
                    hijoDTD.setObligatorio(true);
                    //el * en DTD indica que elemento es opcional y repetible ( de 0 a muchos)
                    if (hijo.endsWith("+)") || hijo.endsWith("+") || hijo.endsWith("*)") || hijo.endsWith("*")) {
                        //devuelve -1 si no lo encuentra    
                        if (hijo.indexOf("*") >= 0) {
                            hijo = hijo.trim().substring(0, hijo.indexOf("*")); 
                        }
                    //Pregunta para sacarle el asterisco o el signo más 
                        if (hijo.indexOf("+") >= 0) {
                            hijo = hijo.trim().substring(0, hijo.indexOf("+"));
                        }
                        hijoDTD.setMuchos(true);//indica que va a tener más de 1 elemento
                    } else {

                        hijoDTD.setMuchos(false);
                    }
                    if (hijo.endsWith("?)")|| hijo.endsWith("?"))
                    {
                        hijoDTD.setObligatorio(false);
                    }
                   
                    hijoDTD.setNombre(hijo);
                    hijoDTD.setRoot(false);
                    
                    listaHijosDTD.add(hijoDTD);

                    root.setListaElementosDTD(listaHijosDTD);
                    elementos.add(root);

                } else {
                    //hijos
                    String renglon[] = lineasDTD[i].split(" "); //guardo las palabras del renglon

                    ElementoDTD hijoDTD = new ElementoDTD();
                    ArrayList<ElementoDTD> listaNietosDTD = new ArrayList<ElementoDTD>();


                    hijoDTD.setNombre(renglon[1].trim());
                    hijoDTD.setRoot(false);
           //         hijoDTD.setObligatorio(true);
                    int j = 0;


                    for (j = 2; j < renglon.length; j++) {
                        //si en el renglon no hay un nieto    
                        //if (renglon[j].trim().length() <= 1 || renglon[j].trim().startsWith(")")) {
                          //  continue;
                        //}
                        /*if (renglon[j].endsWith("?)")|| renglon[j].endsWith("?"))
                        {
                            hijoDTD.setObligatorio(false);
                        }*/
                        if (renglon[j].trim().startsWith("(#") || renglon[j].trim().startsWith("#")) {
                            //es una hoja
                            hijoDTD.setMuchos(false);
                            for(int v=0;v<elementos.get(1).getListaElementosDTD().size();v++)
                            {
                                if(elementos.get(1).getListaElementosDTD().get(v).getNombre().equals(hijoDTD.getNombre()))
                                {
                                    if(elementos.get(1).getListaElementosDTD().get(v).isObligatorio())
                                    {hijoDTD.setObligatorio(true);}
                                    else{
                                        hijoDTD.setObligatorio(false);
                                    }
                                }
                            }
                            break;
                        }
                        
                        hijoDTD.setObligatorio(true);
                        //if no es una hoja
                        String nietos[] = renglon[j].split(",");
                        for (int k = 0; k < nietos.length; k++) {

                            if (nietos[k].trim().startsWith("(")) {

                                nietos[k] = nietos[k].trim().substring(1); //no contempla primer parentesis

                            }

                            if (nietos[k].trim().endsWith(")") || nietos[k].trim().endsWith(")>")) {

                                nietos[k] = nietos[k].trim().substring(0, nietos[k].indexOf(")")); //no contempla ultimo parentesis y signo mayor

                            }
                            ElementoDTD nietoDTD = new ElementoDTD();
                            nietoDTD.setObligatorio(true);
                            // si tiene el signo ? es por que es un elemento opcional
                            if (nietos[k].trim().endsWith("?")) {

                                nietos[k] = nietos[k].trim().substring(0, nietos[k].indexOf("?"));
                                nietoDTD.setObligatorio(false);
                            }
                            /*nietoDTD.setMuchos(false);
                            if (nietos[k].trim().endsWith("+")||nietos[k].trim().endsWith("*") ) {

                                nietos[k] = nietos[k].trim().substring(0, nietos[k].length()-1);
                                nietoDTD.setMuchos(true);
                            }*/

                            nietoDTD.setNombre(nietos[k].trim());
                            nietoDTD.setMuchos(false);
                            nietoDTD.setRoot(false);

                            listaNietosDTD.add(nietoDTD);


                        }// Fin FOR k
                    }// Fin FOR j

                    hijoDTD.setListaElementosDTD(listaNietosDTD);

                    elementos.add(hijoDTD);
                }
            }
        }

        return compararDTD_XML(elementos);
    }

    private static String compararDTD_XML(ArrayList<ElementoDTD> listaElementosDTD) {

        String mensaje = "";
        EntidadXML raiz = null;
        try { //busca el elemento raiz de XML
            for (Iterator<EntidadXML> it = GestorEntidad.listaEntidades.iterator(); it.hasNext();) {
                EntidadXML entidad = it.next();
                if (entidad.isEsRaiz()) {
                    raiz = entidad;
                    break;
                }
            }
        } catch (Exception e) {
            String mesage = e.getMessage();
        }

        String rootXML = raiz.getNombre();
        if (!rootXML.equals(listaElementosDTD.get(0).getNombre())) {
            mensaje = "RAICES NO IGUALES - " + rootXML + " - " + listaElementosDTD.get(0).getNombre();
        }


        for (int i = 0; i < raiz.getHijos().size(); i++) {
            EntidadXML hijo = raiz.getHijos().get(i);

            Iterator<ElementoDTD> itRoot = listaElementosDTD.get(0).getListaElementosDTD().iterator();
            Boolean existeHijo = false;
            
            while (itRoot.hasNext()) {
                ElementoDTD hijoRoot = itRoot.next();
                if (hijoRoot.getNombre().compareTo(hijo.getNombre()) == 0) { //compara que el hijo de la raiz del XML sea igual a alguno de los del DTD
                    existeHijo = true;
                }
                
            }
            if (!existeHijo) {
                
                mensaje = mensaje = mensaje + "\n LA ETIQUETA " + hijo.getNombre() + " NO SE ENCUENTRA DEFINIDA COMO ELEMENTO DE LA RAIZ DEL DTD";
                break;
                
            }

            StringBuffer stringCargaHijo = new StringBuffer();
            stringCargaHijo.append(hijo.getNombre());          
            if (!hijo.getTodosLosAtributos().equals("")) {
                stringCargaHijo.append(" - ");
                stringCargaHijo.append(hijo.getTodosLosAtributos());
            }

            String hijoXML = stringCargaHijo.toString();

            Iterator<ElementoDTD> it = listaElementosDTD.iterator();

            boolean encontro = false;
            ElementoDTD elementoAux = new ElementoDTD();
            while (it.hasNext()) {
                ElementoDTD elemento = it.next();

                if (elemento.getNombre().compareTo(hijoXML) == 0) { //busca coincidencia de las etiquetas hijo
                    encontro = true;
                    elementoAux = elemento;
                }
            }

            if (encontro != true) {
                mensaje = mensaje + "\n LA ETIQUETA " + hijoXML + " NO SE ENCUENTRA DEFINIDA EN EL DTD";
                break;
            }


            for (int j = 0; j < hijo.getHijos().size(); j++) {    //busca coincidencias de elementos de la etiqueta encontrada antes
                EntidadXML e = hijo.getHijos().get(j);
                String elementoXML = e.getNombre();

                boolean encontroAtributo = false;

                Iterator<ElementoDTD> nieto = elementoAux.getListaElementosDTD().iterator();
                while (nieto.hasNext()) {
                    ElementoDTD elemNieto = nieto.next();

                    if (elemNieto.getNombre().compareTo(elementoXML) == 0) {

                        Iterator<ElementoDTD> itListaDTD = listaElementosDTD.iterator();
                        while (itListaDTD.hasNext()) {
                            ElementoDTD elem = itListaDTD.next();
                            if (elementoXML.compareTo(elem.getNombre()) == 0) {
                                encontroAtributo = true;
                                break;
                            }
                        }
                    }
                }
                if (!encontroAtributo) {
                    mensaje = mensaje + "\nEl elemento XML " + elementoXML + " NO SE ENCUENTRA DEFINIDA EN LA DTD";
                    break;
                }
            } //fin 1er FOR
        } //fin for Raiz.gethijos
        
        
        boolean elementoEncontrado = false;
        
        for(int i=1; i< listaElementosDTD.size();i++)
        {
            ElementoDTD elemDTD = listaElementosDTD.get(i);
            elementoEncontrado= false;
            for(int j=0; j< raiz.getHijos().size();j++)
            {
                    EntidadXML elemXML = raiz.getHijos().get(j);
                    if(elemDTD.getNombre().compareTo(elemXML.getNombre())==0)
                    {
                        elementoEncontrado = true;
                        break;
                    }
                    for(int r=0; r< elemXML.getHijos().size();r++)
                    {
                        EntidadXML elemNietoXML = elemXML.getHijos().get(r);
                        if(elemDTD.getNombre().compareTo(elemNietoXML.getNombre())==0)
                        {
                            elementoEncontrado = true;
                            break;
                        }
                    }
                    if(elementoEncontrado == true)
                    {
                        break;
                    }       
            }
            if(elementoEncontrado == false)
            {
                if(elemDTD.isObligatorio())
                {
                    mensaje = mensaje + "\nEl elemento DTD " + elemDTD.getNombre() + " ES OBLIGATORIO Y NO SE ENCUENTRA DEFINIDO EN EL XML";
                    break;
                }
            }
        }
      
        return mensaje;
    }
}
